import {
    _decorator,
    Camera,
    Component,
    EventTouch,
    instantiate,
    KeyCode,
    math,
    Node,
    UITransform,
    v3,
} from 'cc';
import Simulator from './rvo2/Simulator';
import Vector2D from './rvo2/Vector2D';
import RVOMath from './rvo2/RVOMath';
const { ccclass, property } = _decorator;

let tmp1_v3 = v3();
let tmp2_v3 = v3();

// Make sure Simulator is exported from the correct file
@ccclass('ColliderTest')
export class ColliderTest extends Component {
    @property
    speed: number = 10;

    @property(Camera)
    gameCamera: Camera = null;
    @property(Node)
    gameRoot: Node = null;
    @property(Node)
    rectTemplate: Node = null;

    @property([Node])
    nodesArray: Node[] = [];

    simulator = new Simulator();

    targetPosition: Vector2D = null;
    rectMap: Map<number, Node> = new Map();
    isDelMode = false;

    protected onLoad(): void {
        this.simulator.setAgentDefaults(
            //在寻找周围邻居的搜索距离，这个值设置越大，会让小球在越远距离做出避障行为
            200, // neighbor distance (min = radius * radius)

            //寻找周围邻居的最大数目，这个值设置越大，最终计算的速度越 精确，但会加大计算量
            10, // max neighbors

            //计算动态的物体时的时间窗口
            100, // time horizon

            //代表计算静态的物体时的时间窗口，比如在RTS游戏中，小兵 向城墙移动时，没必要做出避障，这个值需要设置的很
            1, // time horizon obstacles

            //代表计算ORCA时的小球的半径，这个值不一定与小球实际显示的半径 一样，偏小有利于小球移动顺畅
            15, // agent radius

            //小球最大速度值
            this.speed, // max speed
            //初始速度
            // 0, // default velocity for x
            // 0, // default velocity for y
        );
    }

    start() {
        this.initGameObject();
    }

    initGameObject() {
        let parent = this.rectTemplate.parent;
        this.rectTemplate.removeFromParent();
        for (let i = 0; i < 5; i++) {
            let x = math.randomRangeInt(-400, 400);
            let y = math.randomRangeInt(-300, 300);
            let rect = instantiate(this.rectTemplate);
            rect.setPosition(x, y, 0);
            rect.parent = parent;

            let sid = this.simulator.addAgent(new Vector2D(x, y));

            if (i === 0) {
                this.simulator.setAgentMaxSpeed(sid, 20);
            }
            this.rectMap.set(sid, rect);
        }

        for (let i = 0; i < this.nodesArray.length; i++) {
            this.generateObstacle(this.nodesArray[i]);
        }

        this.simulator.processObstacles();
    }

    generateObstacle(node: Node) {
        let box = node.getComponent(UITransform)!.getBoundingBox();

        let obs: Vector2D[] = [];
        obs.push(new Vector2D(box.xMin, box.yMin));
        obs.push(new Vector2D(box.xMax, box.yMin));
        obs.push(new Vector2D(box.xMax, box.yMax));
        obs.push(new Vector2D(box.xMin, box.yMax));
        this.simulator.addObstacle(obs);
    }

    processTouch(event: EventTouch) {
        let location = event.getLocation();

        tmp1_v3.set(location.x, location.y);
        this.gameCamera.screenToWorld(tmp1_v3, tmp2_v3);
        this.gameRoot
            .getComponent(UITransform)
            .convertToNodeSpaceAR(tmp2_v3, tmp2_v3);

        // 删除模式
        if (this.isDelMode) {
            let agentNo = this.simulator.queryNearAgent(
                new Vector2D(tmp2_v3.x, tmp2_v3.y),
                15,
            );
            if (agentNo == -1 || !this.rectMap.has(agentNo)) {
                return;
            }
            this.simulator.delAgent(agentNo);
            let rect = this.rectMap.get(agentNo);
            rect.destroy();
            this.rectMap.delete(agentNo);
        } else {
            // 正常更新位置
            if (this.targetPosition) {
                this.targetPosition.set(tmp2_v3.x, tmp2_v3.y);
            } else {
                this.targetPosition = new Vector2D(tmp2_v3.x, tmp2_v3.y);
            }
        }
    }

    protected onEnable(): void {
        this.node.on(Node.EventType.TOUCH_START, this.onTouchBegan, this);
        this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMoved, this);
        this.node.on(Node.EventType.TOUCH_END, this.onTouchEnded, this);
        this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnded, this);
    }

    protected onDisable(): void {}

    update(deltaTime: number) {
        if (!this.targetPosition) {
            return;
        }

        // 更新逻辑坐标
        let agentCount = this.simulator.getNumAgents();
        for (let i = 0; i < agentCount; i++) {
            let agent = this.simulator.agents[i];
            let position = agent.position;
            let goalVector = this.targetPosition.minus(position);
            if (RVOMath.absSq(goalVector) > 1.0) {
                goalVector = RVOMath.normalize(goalVector).scale(
                    agent.maxSpeed,
                );
            }
            agent.prefVelocity = goalVector;
        }
        this.simulator.update(deltaTime);

        // // 更新渲染坐标
        this.rectMap.forEach((v, k) => {
            let pos = this.simulator.getAgentPosition(k);
            v.setPosition(pos.x, pos.y);
        });
    }

    onTouchBegan(event: EventTouch) {
        // if (event.is) {
        //     this.isDelMode = true;
        // } else {
        //     this.isDelMode = false;
        // }
        this.isDelMode = true;
        this.processTouch(event);
    }

    onTouchMoved(event: EventTouch) {
        this.isDelMode = false;
        this.processTouch(event);
    }

    onTouchEnded(event: EventTouch) {
        if (this.targetPosition) {
            this.stopMove();
        }
    }

    onTouchCancel(event: EventTouch) {}

    stopMove() {
        this.targetPosition = null;
        let agentCount = this.simulator.getNumAgents();
        for (let i = 0; i < agentCount; i++) {
            this.simulator.agents[i].prefVelocity.set(0, 0);
        }
    }
}
